package cn.virens.web.components.weixin.session;

import java.time.Duration;
import java.time.Instant;
import java.util.Enumeration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.virens.web.components.weixin.session.standard.WxStandardSession;
import me.chanjar.weixin.common.session.WxSession;

public abstract class AbstractSessionManager implements VirWxSessionManager {
	protected final Logger logger = LoggerFactory.getLogger(getClass());

	private Duration maxInactiveInterval = Duration.ofSeconds(1800);

	public Duration getMaxInactiveInterval() {
		return maxInactiveInterval;
	}

	public void setMaxInactiveInterval(Duration maxInactiveInterval) {
		this.maxInactiveInterval = maxInactiveInterval;
	}

	@Override
	public WxSession getSession(String sessionId) {
		return getStandardSession(sessionId);
	}

	@Override
	public WxSession getSession(String sessionId, boolean create) {
		return getStandardSession(sessionId, create);
	}

	@Override
	public VirWxSession getStandardSession(String sessionId) {
		return getStandardSession(sessionId, true);
	}

	@Override
	public VirWxSession getStandardSession(String sessionId, boolean create) {
		VirWxSession session = findSession(sessionId);

		if (session != null && !session.isExpired()) {
			logger.info("Session has been found:{}", sessionId);

			return wrapupSession(session);
		} else if (session != null && create) {
			logger.info("Session is invalid:{}", sessionId);

			// 移除已经存在的session
			removeStandardSession(session);

			// 重新创建session
			return createSession(sessionId);
		} else if (create) {
			logger.info("Session does not exist:{}", sessionId);

			return createSession(sessionId);
		} else {
			logger.error("Session is invalid or does not exist:{}", sessionId);

			return null;
		}
	}

	protected VirWxSession createSession(String sessionId) {
		WxStandardSession session = new WxStandardSession(sessionId);
		session.setMaxInactiveInterval(maxInactiveInterval);
		session.setLastAccessedTime(Instant.now());
		session.setCreationTime(Instant.now());

		return session;
	}

	protected VirWxSession wrapupSession(VirWxSession session) {
		WxStandardSession wrapSession = new WxStandardSession(session.getSessionId());
		wrapSession.setMaxInactiveInterval(session.getMaxInactiveInterval());
		wrapSession.setCreationTime(session.getCreationTime());
		wrapSession.setLastAccessedTime(Instant.now());

		// 复制session属性值
		Enumeration<String> attributeNames = session.getAttributeNames();
		while (attributeNames.hasMoreElements()) {
			String key = attributeNames.nextElement();
			Object value = session.getAttribute(key);

			wrapSession.setAttribute(key, value);
		}

		return wrapSession;
	}

	protected abstract VirWxSession findSession(String sessionId);
}
